package outils;

import generationTache.IGenerationTache;
import generationTache.generationControle.TacheAperiodiqueCo;
import generationTache.generationControle.TachePeriodiqueCo;

import interfaceGraphique.FenError;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Scanner;

/**
 * Contient tous les divers parseurs de fichiers.
 * @author nicolas rault et matthieu allon
 *
 * @param <T>
 */
public class ManipulationFichier<T extends IGenerationTache> 
{
	/**
	 * Permet de recuperer une liste de tache presente dans le fichier placé en parametre
	 * @param nomFichier nom du fichier ou les taches sont presentes (TacheAp.txt ou TacheP.txt)
	 * @return la liste des taches periodiques ou aperiodiques
	 * @throws FileNotFoundException si le fichier n'existe pas
	 */
	public ArrayList<IGenerationTache> read(String nomFichier) throws FileNotFoundException
	{
		ArrayList<IGenerationTache> listeTache = new ArrayList<IGenerationTache>();
		File file = new File(System.getProperty("user.dir")+"//"+nomFichier);
		Scanner sc = new Scanner(file);
        String entree = "";
        int UP = 0;
        try{
	    	entree = sc.nextLine();
	    	UP = Integer.valueOf(entree.split(":")[1]);
	        while(sc.hasNext())
	        {
	
	        	entree = sc.nextLine();
	        	
	        	if(entree.startsWith("Tache")){
	        		IGenerationTache tacheTmp = null;
	        		if(nomFichier.equals("TacheP.txt"))
	        		{
	        			tacheTmp = new TachePeriodiqueCo(0,0,0, 0);
	        		}
	        		else
	        		{
	        			tacheTmp = new TacheAperiodiqueCo(0,0,0, 0);
	        		}
	        		
	        		tacheTmp.setDi(Integer.valueOf(sc.nextLine().split(" : ")[1]));
	        		tacheTmp.setCi(Integer.valueOf(sc.nextLine().split(" : ")[1]));
	        		tacheTmp.setRi(Integer.valueOf(sc.nextLine().split(" : ")[1]));
	        		tacheTmp.setPi(Integer.valueOf(sc.nextLine().split(" : ")[1]));
	        		tacheTmp.setUp(UP);
	        		listeTache.add(tacheTmp);
	        	}
	        }
        }catch (java.util.NoSuchElementException e) {
			System.out.println(e.toString());
		}
        return listeTache;
		
	}
	
	/**
	 * Permet de sauvegarder les taches dans un fichier
	 * @param listeTache liste des taches a sauvegarder
	 * @param nom fichier ou sont sauvegarde les taches
	 */
	public void sauvegardeTache(ArrayList<T> listeTache, String nom) {
		String path = System.getProperty("user.dir" );
		path = path+"//";
		path = path+nom+".txt";
		path = path.replaceAll("\\\\", "\\\\\\\\");
		try{
			FileWriter fw = new FileWriter (path);
			BufferedWriter bw = new BufferedWriter (fw);
			
			bw.write("Up:"+listeTache.get(0).getUp());
			bw.write("\r\n");
			
			int i =1;
			for(IGenerationTache tache : listeTache)
			{
				bw.write("Tache"+i);
				bw.write("\r\n");
				bw.write("Di : "+tache.getDi());
				bw.write("\r\n");
				bw.write("Ci : "+tache.getCi());
				bw.write("\r\n");
				bw.write("ri : "+tache.getRi());
				bw.write("\r\n");
				bw.write("Pi : "+tache.getPi());
				bw.write("\r\n");
				i++;
			}
			bw.flush();
		}catch (Exception e){
			System.out.println(e.toString());
		}
		
	}
	
	/**
	 * Permet de generer un fichier .ktr valide
	 * @param listeTache liste indiquant l'ordonnancement des taches
	 * @param nom du fichier .ktr
	 * @param nbTache nombre de tache necessaire pour leur activation en debut de fichier .ktr
	 * @param duration parametre a renseigner dans le fichier .ktr
	 */
	public void sauvegardeKiwi(ArrayList<String> listeTache, String nom, int nbTache, int duration)
	{
		System.out.println("Debut de création du fichier kiwi");
		String path = System.getProperty("user.dir" );
		path = path+"//";
		path = path+nom+".ktr";
		path = path.replaceAll("\\\\", "\\\\\\\\");
		try{
			int compteur = 0;
			int tacheEnCours = 0;
			FileWriter fw = new FileWriter (path);
			BufferedWriter bw = new BufferedWriter (fw);
			bw.write("DECIMAL_DIGITS 0");
			bw.write("\r\n");
			bw.write("DURATION "+duration);
			bw.write("\r\n");
			bw.write("PALETTE Rainbow");
			bw.write("\r\n");
			bw.write("ZOOM_X    4");
			bw.write("\r\n");
			bw.write("ZOOM_Y  16");
			bw.write("\r\n");
			bw.write("COLOR EXEC-E 0 orchid4");
			bw.write("\r\n");
			bw.write("\r\n");
			for(int i = 0;i<listeTache.size();i++)
			{
				if (i != 0) 
				{
					if(!listeTache.get(i).equals(listeTache.get(i-1)))
					{
						if(listeTache.get(i).contains("STOP"))
						{
							bw.write(compteur+" DEADLINE "+listeTache.get(i).split(" ")[1]);
							bw.write("\r\n");
						}
						else
						{
							if(!listeTache.get(i).equals("-1"))
							{
								int a = i-1;
								while(listeTache.get(a).contains("STOP"))
								{
									a--;
								}
								if(listeTache.get(a).equals("-1"))
								{
									bw.write(compteur+" EXEC-B "+listeTache.get(i));
									bw.write("\r\n");
									bw.write("\r\n");
									tacheEnCours = Integer.parseInt(listeTache.get(i));
									compteur++;
								}
								else
								{
									bw.write(compteur+" STOP "+tacheEnCours);
									bw.write("\r\n");
									bw.write(compteur+" EXEC-E "+tacheEnCours);
									bw.write("\r\n");
									bw.write(compteur+" READY-E "+tacheEnCours);
									bw.write("\r\n");
									bw.write(compteur+" EXEC-B "+listeTache.get(i));
									bw.write("\r\n");
									bw.write("\r\n");
									tacheEnCours = Integer.parseInt(listeTache.get(i));
									compteur++;
									
								}
							}
							else
							{
								int a = i-1;
								while(listeTache.get(a).contains("STOP"))
								{
									a--;
								}
								if(listeTache.get(a).equals("-1"))
								{
									bw.write(compteur+" EXEC-B "+listeTache.get(i));
									bw.write("\r\n");
									bw.write("\r\n");
									tacheEnCours = Integer.parseInt(listeTache.get(i));
									compteur++;
								}
								else
								{
									if(tacheEnCours != Integer.parseInt(listeTache.get(i)))
									{
										bw.write(compteur+" STOP "+tacheEnCours);
										bw.write("\r\n");
										bw.write(compteur+" EXEC-E "+tacheEnCours);
										bw.write("\r\n");
										bw.write(compteur+" READY-E "+tacheEnCours);
										bw.write("\r\n");
										compteur++;
									}
								}
							}
						}
					}
					else
					{
						compteur++;
					}
						
				}
				else
				{
					int a = 0;
					for(;a<nbTache;a++)
					{
						bw.write("0 READY-B "+a);
						bw.write("\r\n");
					}
					for(a = 0; a<nbTache;a++)
					{
						bw.write("0 START "+a);
						bw.write("\r\n");
					}
					bw.write("0 EXEC-B "+listeTache.get(i));
					bw.write("\r\n");
					bw.write("\r\n");
					tacheEnCours = Integer.parseInt(listeTache.get(i));
					compteur++;
				}
			}
			if(!listeTache.get(listeTache.size()-1).equals("-1"))
			{
				bw.write(compteur+" STOP "+tacheEnCours);
				bw.write("\r\n");
				bw.write(compteur+" EXEC-E "+tacheEnCours);
				bw.write("\r\n");
				bw.write(compteur+" READY-E "+tacheEnCours);
				bw.write("\r\n");
			}
			bw.flush();
		}catch (Exception e){
			System.out.println(e.toString());
		}
		FenError fen = FenError.getInstance("Fichier Kiwi");
		fen.changeLabel("Le fichier Kiwi "+nom+" a été créé avec succès.");
		fen.setLocation(30, 100);
		fen.setVisible(true);
		
		
		System.out.println("Fichier kiwi créé.");
		
	}
	
	/**
	 * Permet de sauvegarder les performances des ordonnanceurs pour les taches aperiodiques
	 * @param ordonnanceur nom de l'ordonnanceur teste
	 * @param borneMin temps de reponse minimum pour une tache
	 * @param borneMax temps de reponse maximum pour une tache
	 * @param moyenne temps moyen de reponse pour une tache
	 * @param nbPreemption nombre de preemption pendant l'ordonnancement
	 * @param nbChangeContexte nombre de changement de contexte pendant l'ordonnancement
	 * @param nbViolationEcheance nombre de violation d'echeance pendant l'ordonnancement
	 */
	public void sauvegardePerformance(String ordonnanceur, int borneMin, int borneMax, int moyenne, int nbPreemption, int nbChangeContexte, int nbViolationEcheance)
	{
		String path = System.getProperty("user.dir" );
		path = path+"//";
		path = path+"ResultatPerformance_" + ordonnanceur + ".log";
		path = path.replaceAll("\\\\", "\\\\\\\\");
		FileWriter fw;
		try 
			{
				fw = new FileWriter (path);
				BufferedWriter bw = new BufferedWriter (fw);
				bw.write("Algorithme d'ordonnancement utilisé :" + ordonnanceur.toUpperCase() + "\r\n");
				bw.write("*******************************************\r\n");
				bw.write("Nombre de violation d'échéances :" + nbViolationEcheance + "\r\n");
				bw.write("*******************************************\r\n");
				bw.write("Nombre de préemptions :" + nbPreemption + "\r\n");
				bw.write("*******************************************\r\n");
				bw.write("Nombre de changement de contextes :" + nbChangeContexte + "\r\n");
				bw.write("*******************************************\r\n");
				bw.write("Temps de réponse : \r\n");
				bw.write("		* Borne minimale :" + borneMin + "\r\n");
				bw.write("		* Borne maximale :" + borneMax + "\r\n");
				bw.write("		* Moyenne :" + moyenne + "\r\n");
				bw.flush();
			} 
		catch (IOException e) 
			{
				System.out.println(e.getMessage());
			}
		
	}
	
}